package main

import (
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"iot-base/common/cache"
	"iot-base/common/ctrltype"
	"iot-base/common/logger"
	"iot-base/devc/common/loader"

	"iot-base/common/modbus"
)

func Serve() {
	loader.SubCtrlHandler(func(pCmd *ctrltype.CtrlCmd) (map[string]interface{}, error) {
		var client modbus.Client
		id := pCmd.ThingID
		thinginfo, _ := cache.GetThing(id)
		protocol, err := loader.GetProtocolParam(id)
		_, ok := Connected[id]
		if !ok {
			client = GetClient(protocol)
			if client == nil {
				return nil, errors.New("Get modbus client err, return nil!")
			}
			Connected[id] = ConnectStatus{true, client}
		} else {
			client = Connected[id].Client
		}
		if client == nil {
			fmt.Println("Creat modbus client err!")
			logger.SLog.Error("Creat modbus client err!")
			return nil, errors.New("Creat modbus client err!")
		}
		if err == nil {
			for _, v := range protocol.ServiceCmds {
				if v.ScanCmd != pCmd.ID {
					continue
				}
				if v.InputParams != nil {
					//定义返回数据
					ret := make(map[string]interface{})
					if fun, ok := WriteFun[thinginfo.Thing.ModelID+"."+v.ScanCmd]; ok {
						ret, err = fun(v, pCmd.Params, client)
						if err != nil {
							return nil, err
						}
						return ret, nil
					}
					for _, p := range *v.InputParams { /*
							for _, n := range p.Param {
								vlue := pCmd.Params[p.ParamID]
								vluetmp, ok := vlue.(string)
								r := PropertyEncodeFun[n.Func](vluetmp, n)
								fmt.Println("convert value:", r)
								if ok {
									res := GetResult("06", n.Begin, n.Count, r, client)
									ret["message"] = string(res)
								} else {
									fmt.Println("covert string err!")
								}
							}*/
						vlue := pCmd.Params[p.ParamID]
						vluetmp, ok := vlue.(string)
						if !ok {
							return nil, errors.New("value is nil or type is not string")
						}
						r := PropertyEncodeFun[p.Param.Func](vluetmp, p.Param)
						fmt.Println("convert value:", r[0])
						if ok {
							if p.Param.Func == "bool" {
								var s uint16
								if r[0] == 255 {
									s = 65280
								} else if r[0] == 0 {
									s = 0
								}
								res, err := GetRes("5", p.Param.Begin, s, nil, client, "scan")
								if err != nil {
									fmt.Println("get result err:", err)
									logger.SLog.Error(err)
									continue
								}
								ret["message"] = string(res)
							} else {
								var sendt uint16
								bytesBuffer := bytes.NewBuffer(r)
								binary.Read(bytesBuffer, binary.BigEndian, &sendt)
								res, err := GetRes("6", p.Param.Begin, sendt, nil, client, "scan")
								if err != nil {
									fmt.Println("get result err:", err)
									logger.SLog.Error(err)
									continue
								}
								ret["message"] = string(res)
							}
						} else {
							fmt.Println("covert string err!")
						}
					}
					fmt.Println("ret", ret)
					return ret, nil
				}
				if v.Scan != nil {
					BeginAddr := v.Scan.Begin
					result, err := GetRes(v.Scan.Code, v.Scan.Begin, v.Scan.Count, nil, client, "serve")
					if err != nil {
						fmt.Println("get result err:", err)
						continue
					}
					ret := make(map[string]interface{})
					for _, out := range v.OutputParams {
						left := (out.OutParam.Begin - BeginAddr) * 2
						right := left + (out.OutParam.Count * 2)
						if int(right) > len(result) && out.OutParam.Func == "bool" {
							fmt.Println("read result count err!")
							logger.SLog.Error(err)
							continue
						}
						if out.OutParam.Func == "bool" {
							right = left + out.OutParam.Count
						}
						if out.OutParam.Size != nil && out.OutParam.IndexOffset != nil {
							size := *out.OutParam.Size
							if size > 0 {
								begin := 0
								if out.OutParam.BeginPos != nil {
									begin = *out.OutParam.BeginPos
								}
								for i := 0; i < size-begin; i++ {
									left := (out.OutParam.Begin - BeginAddr + uint16(*out.OutParam.IndexOffset*i)) * 2
									right := left + (out.OutParam.Count * 2)
									if out.OutParam.Func == "bool" {
										right = left + out.OutParam.Count
									}
									ret[out.ID] = ReadFuncProxy(out.OutParam, result[int(left):int(right)])
								}
							} else {
								res := ReadFuncProxy(out.OutParam, result[int(left):int(right)])
								//if value.PID=="IO status"{
								//	fmt.Printf("offset property:id:%s,pid:%s,sid:%s,index:%v,v:%v\n",id, value.PID, value.SubID, value.Index, res)
								//	fmt.Println("size,offset:",value.ModbusParam.Size,value.ModbusParam.IndexOffset)
								//}
								//if value.PID=="IO status" && (value.SubID == "lock_run"){
								//	fmt.Printf("offset property:id:%s,pid:%s,sid:%s,index:%v,v:%v\n",id, value.PID, value.SubID, value.Index, res)
								//	if value.ModbusParam.Number!=nil{
								//		fmt.Println("number:",*value.ModbusParam.Number)
								//	}
								//}
								//fmt.Printf("property:id:%s,pid:%s,sid:%s,index:%v,v:%v\n",id, value.PID, value.SubID, value.Index, res)
								if res != nil {
									ret[out.ID] = res
								}
							}
						} else {
							//fmt.Println("size:", *value.ModbusParam.Size, "offset:", *value.ModbusParam.IndexOffset)
							//此处解析单个属性使用的解析函数并上报
							res := ReadFuncProxy(out.OutParam, result[int(left):int(right)])
							//if value.PID=="IO status"{
							//	fmt.Printf("offset property:id:%s,pid:%s,sid:%s,index:%v,v:%v\n",id, value.PID, value.SubID, value.Index, res)
							//	fmt.Println("size,offset:",value.ModbusParam.Size,value.ModbusParam.IndexOffset)
							//}
							//fmt.Printf("property:id:%s,pid:%s,sid:%s,index:%v,v:%v\n",id, value.PID, value.SubID, value.Index, res)
							if res != nil {
								ret[out.ID] = res
							}
						}
					}
					return ret, nil
				}
			}
		}
		return nil, nil
	})
}
